"""OpenTelemetry configuration module for WMS3D system.

This module provides the setup and configuration for OpenTelemetry tracing,
including trace providers, exporters, and instrumentations.
"""

import logging
from typing import Optional

from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
from opentelemetry.sdk.resources import SERVICE_NAME, SERVICE_VERSION, Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk.trace.sampling import ParentBased, TraceIdRatioBased

from .config import settings

# Configure logger
logger = logging.getLogger(__name__)


def create_tracer_provider() -> TracerProvider:
    """Create and configure a TracerProvider.

    Returns:
        TracerProvider: Configured tracer provider
    """
    # Create resource with service information
    resource = Resource.create({SERVICE_NAME: "wms3d", SERVICE_VERSION: "1.0.0"})

    # Create tracer provider with resource
    tracer_provider = TracerProvider(
        resource=resource,
        sampler=ParentBased(TraceIdRatioBased(1.0)),  # Sample all traces
    )

    # Configure OTLP exporter
    otlp_exporter = OTLPSpanExporter(
        endpoint=settings.telemetry.otlp_endpoint, insecure=settings.telemetry.otlp_insecure
    )

    # Add batch span processor
    tracer_provider.add_span_processor(BatchSpanProcessor(otlp_exporter))

    return tracer_provider


def setup_telemetry() -> None:
    """Initialize OpenTelemetry tracing for the application.

    This function sets up the global tracer provider and instruments
    the FastAPI application and database connections.
    """
    try:
        # Create and set global tracer provider
        tracer_provider = create_tracer_provider()
        trace.set_tracer_provider(tracer_provider)

        logger.info("OpenTelemetry tracing initialized successfully")
    except Exception as e:
        logger.error(f"Failed to initialize OpenTelemetry tracing: {e}")


def instrument_fastapi(app) -> None:
    """Instrument a FastAPI application with OpenTelemetry.

    Args:
        app: FastAPI application instance
    """
    try:
        FastAPIInstrumentor.instrument_app(app)
        logger.info("FastAPI application instrumented successfully")
    except Exception as e:
        logger.error(f"Failed to instrument FastAPI application: {e}")


def instrument_database(engine) -> None:
    """Instrument a database engine with OpenTelemetry.

    Args:
        engine: SQLAlchemy engine instance
    """
    try:
        SQLAlchemyInstrumentor().instrument(engine=engine)
        logger.info("Database engine instrumented successfully")
    except Exception as e:
        logger.error(f"Failed to instrument database engine: {e}")
